import createElement from "./createElement";
import patchVnode from "./patchVnode";

// 判断两节点是否相同
function checkSameVnode(node1, node2) {
  return node1.sel === node2.sel && node1.key === node2.key;
}

// 两节点的孩子判断  diff核心 
export default function updateChildren(parentNodeElm, newChildren, oldChildren) {
  // 定义四个指针
  // 旧前、旧后
  let oldStartIdx = 0;
  let oldEndIdx = oldChildren.length - 1;
  // 新前、新后
  let newStartIdx = 0;
  let newEndIdx = newChildren.length - 1;

  // 获取四个节点
  // 旧前、旧后 节点
  let oldStartVnode = oldChildren[0];
  let oldEndVnode = oldChildren[oldChildren.length - 1];
  // 新前、新后 节点
  let newStartVnode = newChildren[0];
  let newEndVnode = newChildren[newChildren.length - 1]; 

  // 保存遍历的旧节点的key-index
  let keyMap = null;

  // 开始大while了
  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
    console.log('updateChildren 进行孩子比较')
    // 这里要先判断当前oldVnode等是否为undefined 然后再进行①②③④的比较
    if (oldStartVnode == null || oldStartVnode == undefined) {
      oldStartIdx++;
    } else if (oldEndVnode == null || oldEndVnode == undefined) {
      oldEndIdx--;
    } else if (newStartVnode == null || newStartVnode == undefined) {
      newStartIdx++;
    } else if (newEndVnode == null || newEndVnode == undefined) {
      newEndIdx--;
    }

    // 随后进行四种命中比较

    // ① 新前与旧前
    else if (checkSameVnode(newStartVnode, oldStartVnode)) {
      console.log('① 新前与旧前命中');
      patchVnode(oldStartVnode, newStartVnode);
      oldStartVnode = oldChildren[++oldStartIdx];
      newStartVnode = newChildren[++newStartIdx];
    } 
    // ② 新后与旧后
    else if (checkSameVnode(newEndVnode, oldEndVnode)) {
      console.log('② 新后与旧后命中');
      patchVnode(oldEndVnode, newEndVnode);
      oldEndVnode = oldChildren[--oldEndIdx];
      newEndVnode = newChildren[--newEndIdx];
    }
    // ③ 新后与旧前--- 把该旧节点移动到所有旧孩子节点的最后面
    else if (checkSameVnode(newEndVnode, oldStartVnode)) {
      console.log('③ 新后与旧前命中');
      patchVnode(oldStartVnode, newEndVnode);
      // 移动该旧节点 --- 命中了，可以复用该旧节点，则把该旧节点移动到对应位置（因为这个节点在新节点里面位于后面，所以对应位置就是最后面）
      parentNodeElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling);
      oldStartVnode = oldChildren[++oldStartIdx];
      newEndVnode = newChildren[--newEndIdx];
    }
    // ④ 新前与旧后--- 把该旧节点移动到所有旧孩子节点的最前面（因为新的在最前面啊）
    else if (checkSameVnode(newStartVnode, oldEndVnode)) {
      console.log("④ 新前与旧后命中")
      patchVnode(oldEndVnode, newStartVnode);
      parentNodeElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm);
      oldEndVnode = oldChildren[--oldEndIdx];
      newStartVnode = newChildren[++newStartIdx];
    }
    // 都没有命中 --- 寻找相同的项
    else {
      console.log('四种方式都没有命中---找找oldChildren里面是否存在与newChildren相同的项');
      if (!keyMap) {
        // 收集旧的key -- index
        console.log('收集旧的key -- index 的map--缓存，加快查找')
        keyMap = {};
        for (let i = oldStartIdx; i <= oldEndIdx; i++) {
          const key = oldChildren[i].key;
          if (key !== undefined) {
            keyMap[key] = i;
          }
        }
      } else {
        console.log('从map中查找是否存在当前新节点')
        // 找当前newChildren[i]是否出现在oldChildren里面
        const indexInOld = keyMap[newStartVnode.key];
        if (indexInOld !== undefined) {
          console.log('map里面出现当前new节点--移动map里面对应的旧节点')
          const oldVnodeToMove = oldChildren[indexInOld];
          // 更新节点内容
          patchVnode(oldVnodeToMove, newStartVnode);
          // 将原oldChildren[indexInOld]设置为undefined
          oldChildren[indexInOld] = undefined;
          // old里面存在 --- 将该old移动到所有old最前面
          parentNodeElm.insertBefore(oldVnodeToMove.elm, oldStartVnode.elm);

        } else {
          // old里面不存在 --- 表示当前new是全新的项
          console.log('map里面未出现当前new节点--当前新节点为全新的项')
          parentNodeElm.insertBefore(createElement(newChildren[newStartIdx]), oldStartVnode.elm);
        }
        // 只是在很乱的old里面找到能够复用的。所以只是遍历处理新的
        newStartVnode = newChildren[++newStartIdx];
      }

    }
  }
  // 跳出while了
  if (newStartIdx <= newEndIdx) {
    // 新 children还有剩余 --- 创建添加
    console.log('newChildren还有剩余 --- 创建添加')

    // 把剩余的新孩子创建dom并插入进去--插入到还未处理的旧children之前
    for (let i = newStartIdx; i <= newEndIdx; i++) {
      console.log(oldChildren)
      console.log(oldStartIdx)
      parentNodeElm.insertBefore(createElement(newChildren[i]), oldChildren[oldStartIdx] ? oldChildren[oldStartIdx].elm : null);
    }
  } else if (oldStartIdx <= oldEndIdx) {
    // 老 children还有剩余---删除
    console.log('oldChildren还有剩余---删除')
    for (let i = oldStartIdx; i <= oldEndIdx; i++) {
      // 判断oldChildren[i]是否存在---因为上面map查找中了以后将原old设置为undefined了
      if (oldChildren[i]) {
        parentNodeElm.removeChild(oldChildren[i].elm);
      }
    }
  }

}